/*
 * Graphic.h
 *
 *  Created on: 2012-9-15
 *      Author: yangentao@gmail.com
 */

#ifndef GRAPHIC_H_
#define GRAPHIC_H_

#include <windows.h>

#include "../util/util.h"

class Point: public POINT {
public:
	explicit Point(int x_=0, int y_=0) : x(x_), y(y_) {
	}

};

class Rect: public RECT {
public:
	Rect( int left_ = 0, int top_ = 0, int right_ = 0, int bottom_ = 0 ) :
		left( left_ ), top( top_ ), right( right_ ), bottom( bottom_ ) {
	}

	bool operator==( Rect& rc ) {
		return ( rc.left == left ) && ( rc.right == right ) &&
			   ( rc.top == top ) && ( rc.bottom == bottom );
	}
	bool Contains( Point pt ) {
		return ( pt.x >= left ) && ( pt.x <= right ) &&
			   ( pt.y >= top ) && ( pt.y <= bottom );
	}
	bool Contains( Rect& rc ) {
		return ( rc.left >= left ) && ( rc.right <= right ) &&
			   ( rc.top >= top ) && ( rc.bottom <= bottom );
	}
	bool Intersects( Rect& other ) {
		return ( right > other.left ) && ( left < other.right ) &&
			   ( bottom > other.top ) && ( top < other.bottom );
	}
	void Move( int xDelta, int yDelta ) {
		left += xDelta;
		top += yDelta;
		right += xDelta;
		bottom += yDelta;
	}
	int Width() {
		return right - left;
	}
	int Height() {
		return bottom - top;
	}
	bool Empty() {
		return ( Height() <= 0 ) || ( Width() <= 0 );
	}
};

/**
 * Holds a desired RGB colour.
 */
class Color {
	UINT32 co;
public:
	Color( UINT32 lcol = 0 ) {
		co = lcol;
	}

	Color( UINT32 red, UINT32 green, UINT32 blue ) {
		Set( red, green, blue );
	}
	Color( UINT32 red, UINT32 green, UINT32 blue, UINT32 alpha ) {
		Set( red, green, blue, alpha );
	}

	bool operator==( const Color& other ) const {
		return co == other.co;
	}

	operator COLORREF (){
		return co;
	}
	Color& operator = (COLORREF colorref){
		co = colorref;
		return *this;
	}

	void Set( UINT32 lcol ) {
		co = lcol;
	}

	void Set( UINT32 red, UINT32 green, UINT32 blue ) {
		co = red | ( green << 8 ) | ( blue << 16 );
	}
	void Set( UINT32 red, UINT32 green, UINT32 blue, UINT32 alpha ) {
		co = red | ( green << 8 ) | ( blue << 16 ) | ( alpha << 24 );
	}
	static inline UINT32 ValueOfHex( char ch ) {
		if ( ch >= '0' && ch <= '9' ) {
			return ch - '0';
		} else if ( ch >= 'A' && ch <= 'F' ) {
			return ch - 'A' + 10;
		} else if ( ch >= 'a' && ch <= 'f' ) {
			return ch - 'a' + 10;
		} else {
			return 0;
		}
	}

	//TODO support Alpha
	void Set( const char* val ) {
		if ( *val == '#' ) {
			val++;
		}
		UINT32 r = ValueOfHex( val[0] ) * 16 + ValueOfHex( val[1] );
		UINT32 g = ValueOfHex( val[2] ) * 16 + ValueOfHex( val[3] );
		UINT32 b = ValueOfHex( val[4] ) * 16 + ValueOfHex( val[5] );
		Set( r, g, b );
	}

	UINT32 AsLong() const {
		return co;
	}

	UINT32 GetRed() {
		return co & 0XFF;
	}

	UINT32 GetGreen() {
		return ( co >> 8 ) & 0XFF;
	}

	UINT32 GetBlue() {
		return ( co >> 16 ) & 0XFF;
	}
	UINT32 GetAlpha() {
		return ( co >> 24 ) & 0XFF;
	}
};

;
struct FontParameters {
	String faceName;
	float size;
	int weight;
	bool italic;
	int extraFontFlag;
	int technology;
	int characterSet;

	FontParameters(
		const char* faceName_,
		float size_ = 10,
		int weight_ = 400,
		bool italic_ = false,
		int extraFontFlag_ = 0,
		int technology_ = 0,
		int characterSet_ = 0 ) :

		size( size_ ),
		weight( weight_ ),
		italic( italic_ ),
		extraFontFlag( extraFontFlag_ ),
		technology( technology_ ),
		characterSet( characterSet_ ) {
		faceName = faceName_;
	}

};

class Font {
protected:
	HFONT fid;

	// Private so Font objects can not be copied
	Font(const Font &);
	Font &operator=(const Font &);
public:
	Font();
	virtual ~Font();

	virtual void Create(const char *faceName, int characterSet, int size,
		bool bold, bool italic, int extraFontFlag=0);
	virtual void Release();

	HFONT GetID() { return fid; }
	// Alias another font - caller guarantees not to Release
	void SetID(HFONT fid_) { fid = fid_; }

	operator HFONT(){
		return fid;
	}

};

typedef void* WindowID;
typedef void* GraphicID;

class Graphic {
private:
	// Private so Graphic objects can not be copied
	Graphic( const Graphic& ) {}
	Graphic& operator=( const Graphic& ) {
		return *this;
	}
public:
	Graphic() {}
	virtual ~Graphic() {}
	static Graphic* instance();

	virtual void Init( WindowID wid ) = 0;
	virtual void Init( GraphicID sid, WindowID wid ) = 0;

	virtual void Release() = 0;
	virtual bool isEnable() = 0;
	virtual void PenColour( Color fore ) = 0;
	virtual int LogPixelsY() = 0;
	virtual int DeviceHeightFont( int points ) = 0;
	virtual void MoveTo( int x_, int y_ ) = 0;
	virtual void LineTo( int x_, int y_ ) = 0;
	virtual void Polygon( Point* pts, int npts, Color fore, Color back ) = 0;
	virtual void RectangleDraw( Rect rc, Color fore, Color back ) = 0;
	virtual void FillRectangle( Rect rc, Color back ) = 0;
	virtual void RoundedRectangle( Rect rc, Color fore, Color back ) = 0;
	virtual void AlphaRectangle( Rect rc, int cornerSize, Color fill, int alphaFill,
								 Color outline, int alphaOutline, int flags ) = 0;
	virtual void Ellipse( Rect rc, Color fore, Color back ) = 0;

	virtual void DrawTextNoClip( Rect rc, Font& font_, int ybase, const char* s, int len, Color fore, Color back ) = 0;
	virtual void DrawTextClipped( Rect rc, Font& font_, int ybase, const char* s, int len, Color fore, Color back ) = 0;
	virtual void DrawTextTransparent( Rect rc, Font& font_, int ybase, const char* s, int len, Color fore ) = 0;
	virtual void MeasureWidths( Font& font_, const char* s, int len, int* positions ) = 0;
	virtual int WidthText( Font& font_, const char* s, int len ) = 0;
	virtual int WidthChar( Font& font_, char ch ) = 0;
	virtual int Ascent( Font& font_ ) = 0;
	virtual int Descent( Font& font_ ) = 0;
	virtual int InternalLeading( Font& font_ ) = 0;
	virtual int ExternalLeading( Font& font_ ) = 0;
	virtual int Height( Font& font_ ) = 0;
	virtual int AverageCharWidth( Font& font_ ) = 0;

	virtual void SetClip( Rect rc ) = 0;

};







#endif /* GRAPHIC_H_ */
